import { ElementPropertyConfig, PropertyEntity } from '@farris/ide-property-panel';
import { FormResponseLayoutContext, ResponseLayoutEditorService } from './response-layout-editor';
import { ColumnWidthSettingComponent } from '@farris/response-layout-editor';
import { FormUnifiedColumnLayout } from '../../../container/form/property/editor/form-layout-setting/form-unified-column-layout';
import { IDesignerHost } from '@farris/designer-element';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import { EventEditorService, WebCmdService, DomService, SchemaService, FormBindingType, DesignViewModelService, UniformEditorDataUtil, FormExpression, StateMachineService, DesignViewModelField, DataStatesService, FormSchemaEntityField$Type } from '@farris/designer-services';
import { StyleEditorComponent, BindingEditorComponent, BindingEditorConverter } from '@farris/designer-devkit';
import { ExpressionEditorComponent, ExpressionEditorParam, CodeEditorComponent } from '@farris/designer-devkit';
import { ExpressionProp } from './expression/expression-property-config';
import { DgControl } from '../../../../utils/dg-control';
import { DesignerEnvType, FormBasicService, RefreshFormService, FormVariable } from '@farris/designer-services';
import { Injector } from '@angular/core';
import { EventsEditorFuncUtils } from '../../../../utils/events-editor-func';
import { NotifyService } from '@farris/ui-notify';

export class InputProps extends ExpressionProp {
    /** 布局配置服务 */
    private responseLayoutService: ResponseLayoutEditorService;
    public webCmdService: WebCmdService;
    public domService: DomService;
    public schemaService: SchemaService;
    public dgVMService: DesignViewModelService;
    public formBasicService: FormBasicService;
    public eventEditorService: EventEditorService;
    public controlCreatorService: any;
    public refreshFormService: RefreshFormService;
    public injector: Injector;

    public viewModelId: string;
    public componentId: string;

    /** 控件绑定的模型字段 */
    private dgVMField: DesignViewModelField;

    stateMachineService: StateMachineService;

    dataStatesService: DataStatesService;

    /** Schema-控件映射类 */
    private schemaDOMMapping: any;

    // 在列表中使用控件，列数据
    gridFieldData: any;
    /** 控件绑定的变量 */
    bindingVarible: FormVariable;

    constructor(private serviceHost: IDesignerHost, viewModelId: string, componentId: string) {
        super(serviceHost.getService('DomService'));

        this.domService = serviceHost.getService('DomService');
        this.webCmdService = serviceHost.getService('WebCmdService');
        this.eventEditorService = serviceHost.getService('EventEditorService');
        this.schemaService = serviceHost.getService('SchemaService');
        this.dgVMService = serviceHost.getService('DesignViewModelService');
        this.stateMachineService = serviceHost.getService('StateMachineService');
        this.schemaDOMMapping = serviceHost.getService('SchemaDOMMapping');
        this.formBasicService = serviceHost.getService('FormBasicService');
        this.controlCreatorService = serviceHost.getService('ControlCreatorService');
        this.refreshFormService = serviceHost.getService('RefreshFormService');
        this.injector = serviceHost.getService('Injector');
        this.viewModelId = viewModelId;
        this.componentId = componentId;

    }

    getBasicCommonPropConfig(propertyData: any): PropertyEntity[] {

        const canChangeControlType = this.checkCanChangeControlType(propertyData, this.viewModelId);
        let controlTypeList = [];
        if (!canChangeControlType) {
            controlTypeList = [{
                key: propertyData.type,
                value: (DgControl[propertyData.type] && DgControl[propertyData.type].name) || propertyData.type
            }];
        }

        if (this.dgVMField && this.dgVMField.$type === FormSchemaEntityField$Type.SimpleField) {
            // 绑定字段
            controlTypeList = this.schemaDOMMapping.getEditorTypesByMDataType(this.dgVMField.type.name, this.dgVMField.multiLanguage, 'form', this.formBasicService.envType);
        } else if (this.bindingVarible) {
            // 绑定变量
            controlTypeList = this.schemaDOMMapping.getEditorTypesByMDataType(this.bindingVarible.type, false, 'form', this.formBasicService.envType);
        }

        return [
            {
                propertyID: 'id',
                propertyName: '标识',
                propertyType: 'string',
                description: '组件的id',
                readonly: true
            },
            {
                propertyID: 'type',
                propertyName: '控件类型',
                propertyType: 'select',
                description: '组件的类型',
                readonly: !canChangeControlType,
                iterator: controlTypeList
            }
        ];
    }
    getBasicPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {

        const basicProperties = this.getBasicCommonPropConfig(propertyData);

        const self = this;
        return {
            categoryId: 'basic',
            categoryName: '基本信息',
            properties: basicProperties,
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {

                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'type': {
                        self.changeControlType(propertyData, changeObject.propertyValue);
                        break;
                    }
                }

            },

        };

    }
    /**
     * 获取输入类控件的通用外观属性
     */
    getAppearanceCommonPropConfig(propertyData: any, viewModelId: string, showPosition = 'card'): PropertyEntity[] {
        // 单选组、多选、多选组、开关控件 都不再支持静态文本、占位符
        const notAllowedControlTypes = [
            DgControl.CheckBox.type,
            DgControl.CheckGroup.type,
            DgControl.SwitchField.type,
            DgControl.RadioGroup.type,
            DgControl.Tags.type
        ];

        // 适配标签换行属性
        if (propertyData.appearance && propertyData.appearance.class && propertyData.appearance.class.includes('farris-group-multi-label')) {
            propertyData.labelAutoOverflow = true;
        } else {
            propertyData.labelAutoOverflow = false;
        }

        if (showPosition === 'tableTdEditor') {
            return [
                {
                    propertyID: 'title',
                    propertyName: '标签',
                    propertyType: 'string',
                    description: '标签名称',
                    visible: !propertyData.titleSourceType || propertyData.titleSourceType === 'static'
                },
                {
                    propertyID: 'isTextArea',
                    propertyName: '启用静态文本',
                    propertyType: 'select',
                    description: '是否启用静态文本',
                    defaultValue: false,
                    iterator: [{ key: true, value: '是' }, { key: false, value: '否' }],
                    visible: !notAllowedControlTypes.includes(propertyData.type)
                },
                {
                    propertyID: 'placeHolder',
                    propertyName: '占位符',
                    propertyType: 'string',
                    description: '占位符文本',
                    readonly: false,
                    visible: !notAllowedControlTypes.includes(propertyData.type)
                }
            ];
        }

        this.responseLayoutService = new ResponseLayoutEditorService(this.domService, this.componentId);
        return [
            {
                propertyID: 'responseLayout',
                propertyName: '布局配置',
                propertyType: 'custom',
                description: '布局配置设置',
                editor: ColumnWidthSettingComponent,
                visible: this.responseLayoutService.checkIsInFormComponent(),
                beforeOpenModal: () => this.responseLayoutService.checkCanOpenLayoutEditor(propertyData)
            },
            {
                propertyID: 'appearance',
                propertyName: '样式',
                propertyType: 'cascade',
                cascadeConfig: [
                    {
                        propertyID: 'class',
                        propertyName: 'class样式',
                        propertyType: 'string',
                        description: '组件的CSS样式'
                    },
                    {
                        propertyID: 'style',
                        propertyName: 'style样式',
                        propertyType: 'modal',
                        description: '组件的内容样式',
                        editor: StyleEditorComponent,
                        showClearButton: true
                    }
                ]
            },
            {
                propertyID: 'size',
                propertyName: '尺寸',
                propertyType: 'cascade',
                visible: propertyData.type === DgControl.Avatar.type, // 目前只有头像控件支持size属性
                cascadeConfig: [
                    {
                        propertyID: 'width',
                        propertyName: '宽度（px）',
                        propertyType: 'number',
                        description: '组件的宽度',
                        min: 0,
                        decimals: 0
                    },
                    {
                        propertyID: 'height',
                        propertyName: '高度（px）',
                        propertyType: 'number',
                        description: '组件的高度',
                        min: 0,
                        decimals: 0
                    }
                ]
            },
            {
                propertyID: 'titleSourceType',
                propertyName: '标签类型',
                propertyType: 'select',
                description: '标签的状态',
                iterator: [{ key: 'static', value: '静态' }, { key: 'dynamic', value: '动态' }]
            },
            {
                propertyID: 'title',
                propertyName: '标签',
                propertyType: 'string',
                description: '标签名称',
                visible: !propertyData.titleSourceType || propertyData.titleSourceType === 'static'
            },
            {
                propertyID: 'titleDataSource',
                propertyName: '标签',
                propertyType: 'unity',
                description: '标签数据源',
                editorParams: {
                    controlName: UniformEditorDataUtil.getControlName(propertyData),
                    editorOptions: {
                        types: ['variable'],
                        variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService)
                    },
                },
                visible: propertyData.titleSourceType === 'dynamic'
            },

            {
                propertyID: 'labelAutoWidth', //  f-form-lable-auto
                propertyName: '标签长度自适应',
                propertyType: 'select',
                description: '展示完整标签',
                defaultValue: false,
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }],
                visible: viewModelId === 'root-viewmodel',
                refreshPanelAfterChanged: true
            },
            {
                propertyID: 'titleWidth',
                propertyName: '标签长度',
                propertyType: 'number',
                description: '标签的长度',
                decimals: 0,
                min: 0,
                visible: !propertyData.labelAutoWidth
            },
            // {
            //     propertyID: 'labelAutoOverflow',
            //     propertyName: '标签换行',
            //     propertyType: 'boolean',
            //     description: '标签字数超长时，换行显示',
            //     defaultValue: false,
            //     iterator: [
            //         { key: true, value: '是' },
            //         { key: false, value: '否' }
            //     ],,
            // visible: !propertyData.labelAutoWidth
            // },
            {
                propertyID: 'enableTitleTips',
                propertyName: '启用标签提示',
                propertyType: 'select',
                description: '是否显示标签提示，一般用于前置任务中',
                defaultValue: false,
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }],
            },
            {
                propertyID: 'titleTipsTemplate',
                propertyName: '标签提示内容',
                propertyType: 'modal',
                description: '标签提示内容设置',
                editor: CodeEditorComponent,
                editorParams: {
                    language: 'html'
                },
                visible: propertyData.enableTitleTips
            },
            {
                propertyID: 'placeHolder',
                propertyName: '占位符',
                propertyType: 'string',
                description: '占位符文本',
                readonly: false,
                visible: !notAllowedControlTypes.includes(propertyData.type)
            },
            {
                propertyID: 'holdPlace',
                propertyName: '隐藏时保留位置',
                propertyType: 'select',
                description: '组件隐藏时是否保留原有位置',
                defaultValue: false,
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }]
            },
            {
                propertyID: 'isTextArea',
                propertyName: '启用静态文本',
                propertyType: 'select',
                description: '是否启用静态文本',
                defaultValue: false,
                visible: !notAllowedControlTypes.includes(propertyData.type),
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }]
            },
            {
                propertyID: 'autoHeight',
                propertyName: '自动高度',
                propertyType: 'select',
                description: '控件是否启用自动高度',
                visible: this.checkAutoHeightVisible(notAllowedControlTypes, propertyData),
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }]
            },
            {
                propertyID: 'maxHeight',
                propertyName: '最大高度',
                propertyType: 'number',
                description: '启用自动高度后输入框的最大高度',
                min: 0,
                decimals: 0,
                visible: this.checkAutoHeightVisible(notAllowedControlTypes, propertyData) && propertyData.autoHeight
            }
        ];
    }
    /**
     * 判断自动高度的显示条件
     * @param notAllowedControlTypes 不支持静态文本的控件列表
     * @param propertyData 控件属性
     */
    private checkAutoHeightVisible(notAllowedControlTypes: string[], propertyData: any) {
        // 多行文本和富文本一直显示
        const alwaysShowControls = [DgControl.MultiTextBox.type, DgControl.RichTextBox.type];
        if (alwaysShowControls.includes(propertyData.type)) {
            return true;
        }
        // 其他控件根据是否支持静态文本以及当前是否显示静态文本来控制
        return !notAllowedControlTypes.includes(propertyData.type) && propertyData.isTextArea;
    }

    /**
     * 处理外观类属性的联动
     */
    changeAppearancePropertyRelates(properties: PropertyEntity[], changeObject: FormPropertyChangeObject, propertyData, parameters) {
        if (!changeObject) {
            return;
        }
        switch (changeObject.propertyID) {
            case 'linkedLabelEnabled': {
                const linkedLabelClick = properties.find((p: PropertyEntity) => p.propertyID === 'linkedLabelClick');
                if (linkedLabelClick) {
                    linkedLabelClick.visible = changeObject.propertyValue;
                }
                break;
            }
            case 'title': {
                changeObject.needUpdateControlTreeNodeName = true;
                break;
            }
            case 'titleSourceType': {
                const title = properties.find((p: PropertyEntity) => p.propertyID === 'title');
                const titleDataSource = properties.find(p => p.propertyID === 'titleDataSource');

                if (title) {
                    title.visible = changeObject.propertyValue !== 'dynamic';
                }
                if (titleDataSource) {
                    titleDataSource.visible = changeObject.propertyValue === 'dynamic';
                }
                break;
            }
            case 'enableTitleTips': {
                const titleTipsTemplate = properties.find((p: PropertyEntity) => p.propertyID === 'titleTipsTemplate');
                if (titleTipsTemplate) {
                    titleTipsTemplate.visible = changeObject.propertyValue;
                }
                break;
            }
            case 'responseLayout': {
                this.responseLayoutService.responseLayoutConfig = changeObject.propertyValue;
                const formNodeId = this.responseLayoutService.changeFormControlsByResponseLayoutConfig(this.componentId);
                // changeObject.notApplyToFormDom = true;

                this.updateUnifiedLayoutAfterResponseLayoutChanged(this.componentId);

                // 局部刷新组件
                if (formNodeId) {
                    changeObject.needRefreshedComponentId = formNodeId;
                }
                delete propertyData.responseLayout;

                break;
            }
            case 'class': {
                if (changeObject.parentPropertyID === 'appearance') {

                    this.updateUnifiedLayoutAfterControlChanged(changeObject.propertyValue, propertyData.id, this.componentId);
                }
                break;
            }
            case 'labelAutoOverflow': {
                const labelAutoOverflowClass = ' farris-group-multi-label';
                if (changeObject.propertyValue) {
                    propertyData.appearance.class = propertyData.appearance.class + labelAutoOverflowClass;
                } else {
                    propertyData.appearance.class = propertyData.appearance.class.replace(labelAutoOverflowClass, '');
                }
                break;
            }
            case 'labelAutoWidth': {
                const labelAutoWidthClass = ' f-form-lable-auto';
                if (changeObject.propertyValue) {
                    propertyData.appearance.class = propertyData.appearance.class + labelAutoWidthClass;
                } else {
                    propertyData.appearance.class = propertyData.appearance.class.replace(labelAutoWidthClass, '');
                }
                const titleWidth = properties.find((p: PropertyEntity) => p.propertyID === 'titleWidth');
                if (titleWidth) {
                    titleWidth.visible = !changeObject.propertyValue;
                }
                const labelAutoOverflow = properties.find((p: PropertyEntity) => p.propertyID === 'labelAutoOverflow');
                if (labelAutoOverflow) {
                    labelAutoOverflow.visible = !changeObject.propertyValue;
                }

                break;
            }
            case 'isTextArea': {
                // 多行文本和富文本一直显示
                const alwaysShowControls = [DgControl.MultiTextBox.type, DgControl.RichTextBox.type];
                if (!alwaysShowControls.includes(propertyData.type)) {
                    const autoHeight = properties.find(p => p.propertyID === 'autoHeight');
                    if (autoHeight) {
                        autoHeight.visible = changeObject.propertyValue;
                    }
                    const maxHeight = properties.find(p => p.propertyID === 'maxHeight');
                    if (maxHeight) {
                        maxHeight.visible = autoHeight.visible && changeObject.propertyValue && propertyData.autoHeight;
                    }
                }

                break;
            }
            case 'autoHeight': {
                const maxHeight = properties.find(p => p.propertyID === 'maxHeight');
                if (maxHeight) {
                    maxHeight.visible = changeObject.propertyValue;
                }
                break;
            }
        }
    }
    /**
     * 获取输入类控件的通用行为属性
     */
    getBehaviorCommonPropConfig(propertyData: any, viewModelId: string): PropertyEntity[] {
        // 只有绑定字段的控件支持表达式，绑定变量的控件不支持表达式
        const bindingFieldId = propertyData.binding && propertyData.binding.type === FormBindingType.Form && propertyData.binding.field;
        const expField = this.domService.expressions && this.domService.expressions.find(e => e.fieldId === bindingFieldId);

        // 运行时定制环境中不允许新增变量，因为新增的变量没有入口配置变量值
        const canAddVariable = this.formBasicService.envType === DesignerEnvType.designer;

        // 为了发版，暂时将申报模板子表中的只读、必填属性的表达式选项屏蔽掉
        let showExpInTableTemplate = true;
        const vmBindTo = this.domService.getViewModelById(viewModelId).bindTo;
        if (this.domService.module.templateId === 'nav-table-fillin-form-template' && vmBindTo !== '/') {
            showExpInTableTemplate = false;
        }
        // 视图模型中[字段更新时机]属性现在要在控件上维护，所以在控件上复制一份属性值
        if (bindingFieldId) {
            if (!this.dgVMField) {
                const dgViewModel = this.dgVMService.getDgViewModel(viewModelId);
                this.dgVMField = dgViewModel.fields.find(f => f.id === bindingFieldId);
            }
            propertyData.updateOn = this.dgVMField.updateOn;
        }

        return [
            {
                propertyID: 'binding',
                propertyName: '绑定',
                propertyType: 'modal',
                description: '绑定的表单字段',
                editor: BindingEditorComponent,
                editorParams: { viewModelId, componentId: this.componentId, controlType: propertyData.type, unusedOnly: true },
                converter: new BindingEditorConverter()
            },
            {
                propertyID: 'updateOn',
                propertyName: '绑定字段更新时机',
                propertyType: 'select',
                iterator: [
                    { key: 'change', value: '值变化时' },
                    { key: 'blur', value: '控件失去焦点时' }
                ],
                description: '控件绑定字段的更新时机',
                visible: !!bindingFieldId
            },
            {
                propertyID: 'visible',
                propertyName: '是否可见',
                propertyType: 'unity',
                description: '运行时组件是否可见',
                editorParams: {
                    controlName: canAddVariable ? UniformEditorDataUtil.getControlName(propertyData) : undefined,
                    constType: 'enum',
                    editorOptions: {
                        types: bindingFieldId ? ['const', 'variable', 'custom', 'expression'] : ['const', 'variable', 'custom'],
                        enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
                        variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        newVariableType: 'Boolean',
                        newVariablePrefix: 'is',
                        expressionConfig:
                        {
                            editor: ExpressionEditorComponent,
                            beforeOpenModal: () => this.getExpressionEditorParams(propertyData, '可见编辑器', 'visible'),
                            exprValue: this.getExprValue(expField, propertyData.visible)
                        }
                    }
                }
            },
            {
                propertyID: 'readonly',
                propertyName: '只读',
                propertyType: 'unity',
                description: '是否只读',
                editorParams: {
                    controlName: canAddVariable ? UniformEditorDataUtil.getControlName(propertyData) : undefined,
                    constType: 'enum',
                    editorOptions: {
                        types: bindingFieldId && showExpInTableTemplate ? ['const', 'variable', 'custom', 'expression', 'stateMachine'] : ['const', 'variable', 'custom', 'stateMachine'],
                        enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
                        variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        newVariableType: 'Boolean',
                        newVariablePrefix: 'is',
                        expressionConfig:
                        {
                            editor: ExpressionEditorComponent,
                            beforeOpenModal: () => this.getExpressionEditorParams(propertyData, '只读编辑器', 'readonly'),
                            exprValue: this.getExprValue(expField, propertyData.readonly)
                        },
                        stateMachine: this.stateMachineService.stateMachineMetaData,
                    }
                },
            },

            {
                propertyID: 'require',
                propertyName: '必填',
                propertyType: 'unity',
                description: '是否必填',
                editorParams: {
                    controlName: canAddVariable ? UniformEditorDataUtil.getControlName(propertyData) : undefined,
                    constType: 'enum',
                    editorOptions: {
                        types: bindingFieldId && showExpInTableTemplate ? ['const', 'variable', 'custom', 'expression'] : ['const', 'variable', 'custom'],
                        enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
                        variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        newVariableType: 'Boolean',
                        newVariablePrefix: 'is',
                        expressionConfig:
                        {
                            editor: ExpressionEditorComponent,
                            beforeOpenModal: () => this.getExpressionEditorParams(propertyData, '必填编辑器', 'require'),
                            exprValue: this.getExprValue(expField, propertyData.require)
                        }
                    }
                }
            },
            {
                propertyID: 'tabindex',
                propertyName: '控件Tab索引(从1开始)',
                propertyType: 'number',
                decimals: 0,
                min: -1,
                description: '-1：不启用索引。若启用索引请从1开始配置。',
                visible: ![DgControl.Avatar.type, DgControl.Image.type, DgControl.Tags.type].includes(propertyData.type)
            },
            {
                propertyID: 'hasDefaultFocus',
                propertyName: '具有默认焦点',
                propertyType: 'select',
                description: '是否具有默认焦点',
                iterator: [{ key: true, value: '是' }, { key: false, value: '否' }],
                defaultValue: false,
                visible: ![DgControl.Avatar.type, DgControl.Image.type, DgControl.Tags.type].includes(propertyData.type)
            },
            {
                propertyID: 'focusState',
                propertyName: '焦点状态',
                propertyType: 'string',
                description: '焦点状态设置',
                visible: propertyData.hasDefaultFocus && ![DgControl.Avatar.type, DgControl.Image.type, DgControl.Tags.type].includes(propertyData.type)
            }
        ];
    }
    /**
     * 行为类属性的变更联动方法
     */
    changeBehaviorPropertyRelates(
        properties: PropertyEntity[], changeObject: FormPropertyChangeObject,
        propertyData: any, parameters, showPosition = 'card') {
        if (!changeObject) {
            return;
        }
        switch (changeObject.propertyID) {
            case 'binding': {
                this.updateControlDomAfterChangingBinding(propertyData, parameters, this.viewModelId, changeObject);
                break;
            }
            case 'hasDefaultFocus': {
                const focusState = properties.find(p => p.propertyID === 'focusState');
                if (focusState) {
                    focusState.visible = changeObject.propertyValue && ![DgControl.Avatar.type, DgControl.Image.type, DgControl.Tags.type].includes(propertyData.type);
                }
                break;
            }
            case 'readonly': case 'visible': case 'require': {
                // 属性值从表达式切换为其他类型：需要清空DOM中的表达式配置
                const newValueType = changeObject.propertyValue && changeObject.propertyValue.type;
                this.clearExpression(newValueType, propertyData, changeObject.propertyID);
                break;
            }
            case 'updateOn': {
                // 字段更新时机
                const dgVM = this.dgVMService.getDgViewModel(this.viewModelId);
                if (dgVM && this.dgVMField) {
                    dgVM.changeField(this.dgVMField.id, { updateOn: changeObject.propertyValue });
                }
                // delete propertyData.updateOn;

                break;
            }

        }

    }

    /**
     * 修改绑定后要同步变更控件path属性，若是帮助控件还要变更数据源属性并同步viewModel
     */
    updateControlDomAfterChangingBinding(propertyData: any, parameters: any, viewModelId: string, changeObject: FormPropertyChangeObject) {
        const selectedData = parameters && parameters.selectedData;
        if (!selectedData) {
            return;
        }
        // 变更path属性
        propertyData.path = selectedData.bindingPath;

        // 切换当前dgVMField
        this.checkCanChangeControlType(propertyData, viewModelId);

        // 帮助控件变更dataSource.uri属性
        if (propertyData.type === DgControl.LookupEdit.type && propertyData.dataSource && propertyData.dataSource.uri) {
            const uri = propertyData.dataSource.uri;
            const index = uri.indexOf('.');
            if (index < 0) {
                return;
            }

            if (propertyData.binding.type === FormBindingType.Form) {
                const newUri = uri.slice(0, index) + '.' + selectedData.bindingField;
                propertyData.dataSource.uri = newUri;

                // 同步viewModel Field
                const dgViewModel = this.dgVMService.getDgViewModel(viewModelId);
                dgViewModel.changeField(propertyData.binding.field, { editor: { dataSource: propertyData.dataSource } });
            } else {
                const newUri = uri.slice(0, index) + '.' + selectedData.code;
                propertyData.dataSource.uri = newUri;
            }

        }
        if (propertyData.type === DgControl.LookupEdit.type) {
            propertyData.lookupPickingExpression = null;
        }
        // 切换绑定后涉及到了表达式的移除，需要触发属性面板的更新
        if (parameters.expressionCleared) {
            changeObject.needRefreshedComponentId = propertyData.id;
        }

        // 刷新实体树
        this.refreshFormService.refreshSchamaTree.next();
    }
    /**
     * 修改某一输入控件的样式后更新Form的统一布局配置
     * @param controlClass 控件样式
     * @param controlId 控件Id
     * @param componentId 控件所在组件id
     */
    private updateUnifiedLayoutAfterControlChanged(controlClass: string, controlId: string, componentId: string) {

        const controlClassArray = controlClass.split(' ');

        let colClass = controlClassArray.find(item => /^col-([1-9]|10|11|12)$/.test(item));
        let colMDClass = controlClassArray.find(item => /^col-md-([1-9]|10|11|12)$/.test(item));
        let colXLClass = controlClassArray.find(item => /^col-xl-([1-9]|10|11|12)$/.test(item));
        let colELClass = controlClassArray.find(item => /^col-el-([1-9]|10|11|12)$/.test(item));

        colClass = colClass || 'col-12';
        colMDClass = colMDClass || 'col-md-' + colClass.replace('col-', '');
        colXLClass = colXLClass || 'col-xl-' + colMDClass.replace('col-md-', '');
        colELClass = colELClass || 'col-el-' + colXLClass.replace('col-xl-', '');

        const latestControlLayoutConfig = {
            id: controlId,
            columnInSM: parseInt(colClass.replace('col-', ''), 10),
            columnInMD: parseInt(colMDClass.replace('col-md-', ''), 10),
            columnInLG: parseInt(colXLClass.replace('col-xl-', ''), 10),
            columnInEL: parseInt(colELClass.replace('col-el-', ''), 10),
        };

        this.updateUnifiedLayoutAfterResponseLayoutChanged(componentId, latestControlLayoutConfig);
    }

    /**
     * 修改控件布局配置后更新Form统一布局配置
     * @param componentId 组件Id
     * @param controlLayoutConfig 某单独变动的控件配置项，FormResponseLayoutContext类型
     */
    private updateUnifiedLayoutAfterResponseLayoutChanged(componentId: string, controlLayoutConfig?: any): FormUnifiedColumnLayout {
        const componentNode = this.domService.getComponentById(componentId);
        if (!componentNode || !componentNode.componentType || !componentNode.componentType.startsWith('form')) {
            return;
        }
        const formNode = this.domService.selectNode(componentNode, item => item.type === DgControl.Form.type);
        if (!formNode || !formNode.unifiedLayout) {
            return;
        }

        const responseLayoutConfig: FormResponseLayoutContext[] = [];

        this.responseLayoutService.getFormResonseLayoutConfig(formNode, responseLayoutConfig, 1);

        if (controlLayoutConfig) {
            const changedControl = responseLayoutConfig.find(c => c.id === controlLayoutConfig.id);
            Object.assign(changedControl, controlLayoutConfig);
        }

        // 收集每种屏幕下的列数
        const columnInSMArray = responseLayoutConfig.map(config => config.columnInSM);
        const columnInMDArray = responseLayoutConfig.map(config => config.columnInMD);
        const columnInLGArray = responseLayoutConfig.map(config => config.columnInLG);
        const columnInELArray = responseLayoutConfig.map(config => config.columnInEL);

        // 只有每个控件的宽度都一样时，才认为form上有统一宽度，否则认为是自定义的控件宽度，此处传递null
        const uniqueColClassInSM = this.checkIsUniqueColumn(columnInSMArray) ? columnInSMArray[0] : null;
        const uniqueColClassInMD = this.checkIsUniqueColumn(columnInMDArray) ? columnInMDArray[0] : null;
        const uniqueColClassInLG = this.checkIsUniqueColumn(columnInLGArray) ? columnInLGArray[0] : null;
        const uniqueColClassInEL = this.checkIsUniqueColumn(columnInELArray) ? columnInELArray[0] : null;


        Object.assign(formNode.unifiedLayout, {
            uniqueColClassInSM,
            uniqueColClassInMD,
            uniqueColClassInLG,
            uniqueColClassInEL
        });
    }
    /**
     * 校验宽度样式值是否一致
     */
    private checkIsUniqueColumn(columnsInScreen: number[]) {
        const keySet = new Set(columnsInScreen);
        const exclusiveKeys = Array.from(keySet);

        if (exclusiveKeys.length === 1) {
            return true;
        }
        return false;
    }


    /**
     * 获取表达式编辑需要的参数：在属性面板弹出表达式窗口时调用
     */
    private getExpressionEditorParams(propertyData: any, modalTitle: string, expressionType: string) {

        let expressionStr = null;

        const bindingFieldId = propertyData.binding && propertyData.binding.field;

        const expressionParams: ExpressionEditorParam = {
            modalTitle: modalTitle || '表达式编辑器',
            fieldId: bindingFieldId,
            viewModelId: this.viewModelId,
            expType: expressionType
        };

        // 必填表达式需要配置提示消息
        if (expressionType === 'require') {
            expressionParams.message = '';
        }


        const propertyValue = propertyData[expressionType];
        if (propertyValue && propertyValue.expressionId && bindingFieldId) {
            const expField = this.domService.expressions.find(e => e.fieldId === bindingFieldId);

            // 检测到现有的表达式配置
            if (expField) {
                const originalExpConfig = expField.expression.find(exp => exp.id === propertyValue.expressionId);
                expressionStr = originalExpConfig.value;

                if (expressionType === 'require') {
                    expressionParams.message = originalExpConfig.message;
                }
            }
        }

        return {
            editorParams: expressionParams,
            value: expressionStr
        };
    }

    /**
     * 获取属性编辑器需要的初始绑定值
     * @param expField 表达式配置字段
     * @param propertyValue 属性值
     */
    private getExprValue(expField: FormExpression, propertyValue: any) {
        let expressionStr = null;
        if (propertyValue && propertyValue.expressionId && expField) {
            const originalExpConfig = expField.expression.find(exp => exp.id === propertyValue.expressionId);
            expressionStr = originalExpConfig && originalExpConfig.value;

        }

        return {
            type: 'expression',
            value: {
                value: expressionStr,
                parameters: propertyValue && propertyValue.expressionId,
                type: 'Expression'
            }
        };
    }
    /**
     * 校验控件是否支持切换类型
     * @param control 控件
     */
    private checkCanChangeControlType(propertyData: any, viewModelId: string): boolean {
        // 没有绑定信息的控件
        if (!propertyData.binding) {
            return false;
        }

        // 不可编辑的列表、树列不能切换类型
        if (propertyData.type === DgControl.TreeGridField.type || (propertyData.type === DgControl.GridField.type && !propertyData.editor)) {
            return false;
        }
        if (propertyData.binding.type === 'Variable') {
            this.bindingVarible = this.domService.getVariableById(propertyData.binding.field);
            // vm中已移除的变量
            if (!this.bindingVarible) {
                return false;
            }

        } else {
            const dgViewModel = this.dgVMService.getDgViewModel(viewModelId);
            this.dgVMField = dgViewModel.fields.find(f => f.id === propertyData.binding.field);

            // schema中已移除的字段 或者绑定复杂类型的字段
            if (!this.dgVMField || this.dgVMField.$type !== FormSchemaEntityField$Type.SimpleField) {
                return false;
            }

        }
        return true;

    }

    /**
     * 清除原表达式
     */
    clearExpression(newValueType: string, propertyData: any, propertyID: string) {
        if (newValueType !== 'Expression') {
            const bindingFieldId = propertyData.binding && propertyData.binding.field;
            const exp = this.domService.expressions.find(e => e.fieldId === bindingFieldId);
            if (!exp || !exp.expression) {
                return;
            }
            exp.expression = exp.expression.filter(e => e.type !== propertyID);
        }

    }
    /**
     * 卡片控件：切换控件类型后事件
     * @param propertyData 控件DOM属性
     * @param newControlType 新控件类型
     */
    changeControlType(propertyData, newControlType: string) {
        // 1、定位控件父容器
        const cmp = this.domService.getComponentById(this.componentId);
        const parentContainer = this.getControlParentContainer(propertyData.id, cmp);
        if (!parentContainer) {
            return;
        }
        const index = parentContainer.contents.findIndex(c => c.id === propertyData.id);
        const oldControl = parentContainer.contents[index];

        let newControl;
        // 绑定字段
        if (this.dgVMField) {
            // ①、记录viewModel 变更---全量替换editor
            const dgViewModel = this.dgVMService.getDgViewModel(this.viewModelId);
            dgViewModel.changeField(this.dgVMField.id, {
                editor: {
                    $type: newControlType
                },
                name: this.dgVMField.name,
                require: this.dgVMField.require,
                readonly: this.dgVMField.readonly
            }, false);
            // ② 创建新控件
            newControl = this.controlCreatorService.createControlBySchemaFeild(this.dgVMField, cmp.componentType);
        } else {
            // 绑定变量
            // ① 记录viewModel 变更---全量替换editor
            const vmVariable = this.domService.getViewModelFieldById(this.viewModelId, this.bindingVarible.id);
            Object.assign(vmVariable, {
                editor: {
                    $type: newControlType
                }
            });
            // ② 创建新控件
            newControl = this.controlCreatorService.createControlByVariable(this.bindingVarible, cmp.componentType, newControlType, this.componentId);
        }


        //  保留原id和isRTControl、样式等属性
        Object.assign(newControl, {
            id: oldControl.id,
            isRTControl: !!oldControl.isRTControl,
            appearance: oldControl.appearance,
            size: oldControl.size,
            titleSourceType: oldControl.titleSourceType,
            title: oldControl.title,
            titleDataSource: oldControl.titleDataSource,
            titleWidth: oldControl.titleWidth,
            labelAutoWidth: oldControl.labelAutoWidth,
            labelAutoOverflow: oldControl.labelAutoOverflow,
            enableTitleTips: oldControl.enableTitleTips,
            titleTipsTemplate: oldControl.titleTipsTemplate,
            isTextArea: newControl.isTextArea && oldControl.isTextArea,
            placeHolder: oldControl.placeHolder,
            holdPlace: oldControl.holdPlace,
            readonly: oldControl.readonly,
            require: oldControl.require,
            visible: oldControl.visible
        });

        // 4、替换控件
        parentContainer.contents.splice(index, 1, newControl);

        // 5、触发父容器刷新
        this.refreshFormService.refreshFormDesigner.next(parentContainer.id);

        return parentContainer.id;

    }

    /**
     * 获取控件：以contents为节点进行定位
     * @param controlId 控件ID
     * @param domJson 容器
     */
    private getControlParentContainer(controlId: string, domJson: any) {
        let container;
        if (!domJson || !domJson.contents || domJson.contents.length === 0) {
            return null;
        }

        for (const content of domJson.contents) {
            if (content.id === controlId) {
                container = domJson;
                return domJson;
            }
            container = this.getControlParentContainer(controlId, content);
            if (container) {
                return container;
            }
        }
    }


    /**
     * 输入控件扩展区域属性配置
     * @param propertyData 属性值
     * @param viewModelId viewModelId
     * @returns ElementPropertyConfig
     */
    getInputAppendPropertyConfig(propertyData: any, viewModelId: string, showPosition = 'card'): ElementPropertyConfig {
        const props = [
            {
                propertyID: 'enableAppend',
                propertyName: '启用扩展区域',
                propertyType: 'unity',
                description: '是否启用扩展区域',
                editorParams: {
                    controlName: UniformEditorDataUtil.getControlName(propertyData),
                    constType: 'enum',
                    editorOptions: {
                        types: ['const', 'variable', 'custom'],
                        enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
                        variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        newVariableType: 'Boolean',
                        newVariablePrefix: 'is'
                    }
                },
            },
            {
                propertyID: 'inputAppendText',
                propertyName: '扩展文本',
                propertyType: 'modal',
                description: '扩展区域展示的文本内容',
                editor: CodeEditorComponent,
                editorParams: {
                    language: 'html'
                }
            },
            {
                propertyID: 'inputAppendType',
                propertyName: '扩展类型',
                propertyType: 'select',
                description: '扩展区域展示的文本内容',
                iterator: [{ key: 'text', value: '静态文本' }, { key: 'button', value: '按钮' }]
            },
            {
                propertyID: 'inputAppendDisabled',
                propertyName: '是否禁用',
                propertyType: 'unity',
                description: '是否禁用扩展区域',
                editorParams: {
                    controlName: UniformEditorDataUtil.getControlName(propertyData),
                    constType: 'enum',
                    editorOptions: {
                        types: ['const', 'variable', 'custom'],
                        enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
                        variables: UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        getVariables: () => UniformEditorDataUtil.getVariables(viewModelId, this.domService),
                        newVariableType: 'Boolean',
                        newVariablePrefix: 'is'
                    }
                }
            }
        ];

        this.checkAppendVisible(props, propertyData);
        const self = this;

        const config = {
            categoryId: 'inputAppend',
            categoryName: '扩展区域',
            properties: props,
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject && changeObject.propertyID) {
                    case 'enableAppend': case 'inputAppendType': {
                        self.checkAppendVisible(this.properties, propertyData);
                        break;
                    }
                }
            }
        };

        if (showPosition !== 'card') {
            Object.assign(config, {
                categoryId: showPosition + '_' + config.categoryId,
                propertyData,
                enableCascade: true,
                parentPropertyID: 'editor',
                tabId: showPosition,
                tabName: '编辑器'
            });
        }
        return config;
    }

    /**
     * 控制扩展区域属性显隐
     * @param props 属性配置
     * @param propertyData 属性值
     */
    private checkAppendVisible(props: PropertyEntity[], propertyData: any) {
        props.forEach(prop => {
            switch (prop.propertyID) {
                case 'inputAppendText': case 'inputAppendType': {
                    prop.visible = propertyData.enableAppend !== false;
                    break;
                }
                case 'inputAppendDisabled': case 'inputAppendClickEvent': {
                    prop.visible = propertyData.enableAppend !== false && propertyData.inputAppendType === 'button';
                    break;
                }
            }
        });
    }

    /**
     * 列编辑器类型切换属性
     */
    getGridFieldEditorTypePropertyConfig(gridFieldData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        const propertyData = gridFieldData.editor;
        this.gridFieldData = gridFieldData;


        const canChangeControlType = this.checkCanChangeControlType(propertyData, viewModelId);
        let controlTypeList = [];

        if (canChangeControlType) {
            controlTypeList = this.schemaDOMMapping.getEditorTypesByMDataType(this.dgVMField.type.name, this.dgVMField.multiLanguage, 'dataGrid', this.formBasicService.envType);
        } else if (this.dgVMField && this.dgVMField.$type === FormSchemaEntityField$Type.ComplexField) {
            controlTypeList = [{
                key: propertyData.type,
                value: (DgControl[propertyData.type] && DgControl[propertyData.type].name) || propertyData.type
            }];

        }
        if (controlTypeList.length === 0) {
            return;
        }
        return {
            categoryId: 'gridFieldEditor_editorType',
            categoryName: '编辑器类型',
            propertyData,
            enableCascade: true,
            parentPropertyID: 'editor',
            tabId: 'gridFieldEditor',
            tabName: '编辑器',
            properties: [
                {
                    propertyID: 'type',
                    propertyName: '编辑器类型',
                    propertyType: 'select',
                    readonly: !canChangeControlType,
                    iterator: controlTypeList
                }
            ],
            setPropertyRelates(changeObject: FormPropertyChangeObject, prop, parameters) {
                if (!changeObject) {
                    return;
                }
                switch (changeObject && changeObject.propertyID) {
                    case 'type': {
                        self.changeGridFieldEditorType(changeObject.propertyValue, viewModelId);
                        break;
                    }
                }
            }
        };
    }
    /**
     * datagrid field:列编辑器类型切换后事件
     * @param newControlType 新控件类型
     * @param viewModelId 视图模型ID
     */
    changeGridFieldEditorType(newControlType: string, viewModelId: string) {

        // 1、记录viewModel 变更---全量替换editor
        const dgViewModel = this.dgVMService.getDgViewModel(viewModelId);
        dgViewModel.changeField(this.dgVMField.id, {
            editor: {
                $type: newControlType
            },
            name: this.dgVMField.name,
            require: this.dgVMField.require,
            readonly: this.dgVMField.readonly
        }, false);


        // 2、定位列表
        const cmp = this.domService.getComponentByVMId(viewModelId);
        const grid = this.domService.selectNode(cmp, item => item.type === DgControl.DataGrid.type || item.type === DgControl.TreeGrid.type);

        if (!grid) {
            return;
        }
        // 3、创建新列
        const editable = grid.fieldEditable;
        const dataField = this.dgVMField.bindingPath;
        const gridFieldType = grid.type === DgControl.DataGrid.type ? DgControl.GridField.type : DgControl.TreeGridField.type;

        const newField = this.controlCreatorService.createGridFieldBySchemaFeild(this.dgVMField, dataField, editable,
            gridFieldType, grid.controlSource);

        // 4、替换列编辑器
        const index = grid.fields.findIndex(c => c.id === this.gridFieldData.id);
        if (index > -1 && grid.fields[index].editor) {
            grid.fields[index].editor = Object.assign(newField.editor, {
                id: grid.fields[index].editor.id,
                isRTControl: !!grid.fields[index].editor.isRTControl,
                title: grid.fields[index].editor.title
            });
        }


    }

    /**
     * 追加列编辑器内的必填、字段更新时机属性
     * @param editorProp 列编辑器属性分类
     * @param gridFieldEditorData  列编辑器数据
     * @param viewModelId viewModelId
     */
    appendBehaviorPropsForGridFieldEditor(editorProp: ElementPropertyConfig, gridFieldEditorData: any, viewModelId: string) {
        // 获取绑定字段对应的表达式
        const bindingFieldId = gridFieldEditorData.binding && gridFieldEditorData.binding.type === FormBindingType.Form && gridFieldEditorData.binding.field;
        const expField = this.domService.expressions && this.domService.expressions.find(e => e.fieldId === bindingFieldId);

        // 视图模型中[字段更新时机]属性现在要在控件上维护，所以在控件上复制一份属性值
        if (bindingFieldId && !gridFieldEditorData.updateOn && this.dgVMField) {
            gridFieldEditorData.updateOn = this.dgVMField.updateOn;
        }

        editorProp.properties.unshift(
            {
                propertyID: 'require',
                propertyName: '是否必填',
                propertyType: 'unity',
                description: '是否必填',
                editorParams: {
                    controlName: UniformEditorDataUtil.getControlName(gridFieldEditorData),
                    constType: 'enum',
                    newVariableType: 'Boolean',
                    newVariablePrefix: 'is',
                    editorOptions: {
                        types: ['const', 'expression'],
                        enums: [{ key: true, value: '是' }, { key: false, value: '否' }],
                        expressionConfig:
                        {
                            editor: ExpressionEditorComponent,
                            beforeOpenModal: () => this.getExpressionEditorParams(gridFieldEditorData, '必填编辑器', 'require'),
                            exprValue: this.getExprValue(expField, gridFieldEditorData.require)
                        }
                    }
                }
            },
            // {
            //     propertyID: 'updateOn',
            //     propertyName: '绑定字段更新时机',
            //     propertyType: 'select',
            //     iterator: [
            //         { key: 'change', value: '值变化时' },
            //         { key: 'blur', value: '控件失去焦点时' }
            //     ],
            //     description: '控件绑定字段的更新时机'
            // }
        );
    }
    /**
     * 组装输入类控件的交互面板：包含标签超链、绑定字段值变化前后事件等。
     * @param propertyData 属性值
     * @param viewModelId 视图模型id
     * @param showPosition 面板展示位置
     * @param customEvent 输入控件特有的事件配置
     */
    public getEventPropertyConfig(propertyData: any, viewModelId: string, showPosition = 'card', customEvent?: {
        customEventList?: { label: string, name: string }[],
        setPropertyRelates?: (propertyData) => void
    }): ElementPropertyConfig {
        const self = this;
        const domService = this.domService;
        const webCmdService = this.webCmdService;
        const formBasicService = this.formBasicService;
        const eventEditorService = this.eventEditorService;
        // 静态事件
        let eventList = [];
        if (customEvent && customEvent.customEventList) {
            eventList = eventList.concat(customEvent.customEventList);
        }
        // 动态事件
        eventList = this.switchEvents(propertyData, eventList);

        // 追加值变化、标签超链事件
        this.appendFieldValueChangeEvents(propertyData, eventList);
        this.appendLinkLabelClickEvent(propertyData, eventList, showPosition);



        const config = {
            categoryId: 'eventsEditor',
            categoryName: '事件',
            hideTitle: true,
            properties: EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList, this.switchEvents),
            tabId: 'commands',
            tabName: '交互',
            setPropertyRelates(changeObject: FormPropertyChangeObject, data: any, parameters: any) {
                delete propertyData[viewModelId];
                if (parameters) {
                    parameters.setPropertyRelates = this.setPropertyRelates; // 添加自定义方法后，调用此回调方法，用于处理联动属性
                    parameters.controlInfo = { type: self.getControlMethodType(propertyData), name: propertyData.title };  // 暂存控件信息，用于自动创建新方法的方法编号和名称

                    EventsEditorFuncUtils.saveRelatedParameters(eventEditorService, domService, webCmdService, propertyData, viewModelId, parameters['events'], parameters);
                    this.properties = EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, parameters['events'], self.switchEvents);
                }

                if (customEvent && customEvent.setPropertyRelates) {
                    customEvent.setPropertyRelates(propertyData);
                }

                // 联动修改【启用标签超链接】属性
                if (showPosition === 'gridFieldEditor' && self.gridFieldData) {
                    // 列表列的超链接属性是在GridField上的，不是在editor里，所以这里要单独赋值
                    const previousLinkedLabelEnabled = self.gridFieldData.linkedLabelEnabled;
                    self.gridFieldData.linkedLabelClick = propertyData.linkedLabelClick;
                    self.gridFieldData.linkedLabelEnabled = !!propertyData.linkedLabelClick;
                    // 清除editor内的超链属性
                    propertyData.linkedLabelClick = null;
                    propertyData.linkedLabelEnabled = false;
                    if (!previousLinkedLabelEnabled && self.gridFieldData.linkedLabelEnabled) {
                        const notifyService = self.injector.get(NotifyService);
                        notifyService.warning('启用标签超链事件后，列模板失效！');
                    }
                } else {
                    propertyData.linkedLabelEnabled = !!propertyData.linkedLabelClick;
                }


                // 同步视图模型值变化事件
                const dgVM = self.dgVMService.getDgViewModel(self.viewModelId);
                if (dgVM && self.dgVMField) {
                    dgVM.changeField(self.dgVMField.id, { valueChanging: propertyData.fieldValueChanging, valueChanged: propertyData.fieldValueChanged });
                }
            }
        };
        if (showPosition !== 'card') {
            Object.assign(config, {
                categoryId: showPosition + '_' + config.categoryId,
                propertyData,
                enableCascade: true,
                parentPropertyID: 'editor'
            });
        }

        return config;
    }
    /**
     * 处理交互面板中的动态事件
     * @param propertyData 属性值
     * @param eventList 事件列表
     */
    switchEvents(propertyData: any, eventList: any[]) {
        // 根据是否【启用扩展区域】属性判断是否显示【扩展按钮点击事件】
        if (propertyData.enableAppend !== false && propertyData.inputAppendType === 'button') {
            const eventListExist = eventList.find(eventListItem => eventListItem.label === 'inputAppendClickEvent');
            if (!eventListExist) {
                eventList.push(
                    {
                        label: 'inputAppendClickEvent',
                        name: '扩展按钮点击事件'
                    }
                );
            }
        } else {
            if (eventList.length !== 0) {
                eventList = eventList.filter(eventListItem => eventListItem.label !== 'inputAppendClickEvent');
            }
        }

        return eventList;

    }
    /**
     * 将标签超链属性追加到交互面板，
     */
    private appendLinkLabelClickEvent(propertyData: any, eventList: any[], showPosition: string) {
        // 只有卡片和可编辑列表中有标签超链
        if (showPosition !== 'card' && showPosition !== 'gridFieldEditor') {
            return;
        }
        // 部分控件没有标签
        const controlsWithoutLabel = [DgControl.Avatar.type, DgControl.Image.type];
        if (controlsWithoutLabel.includes(propertyData.type)) {
            return;
        }

        eventList.push({
            label: 'linkedLabelClick',
            name: '标签超链事件'
        });

        // 因为需要将GridField editor内的事件与GridField上超链事件合并起来展示到交互面板中，所以这里先将事件复制到editor里去
        if (showPosition === 'gridFieldEditor' && this.gridFieldData) {
            propertyData.linkedLabelClick = this.gridFieldData.linkedLabelClick;
        }

    }
    /**
     * 将字段值变化前事件、变化后事件追加到交互面板
     * 注意：因为绑定字段值变化后事件与下拉框的值变化事件(valueChanged)重名，所以这里将事件label都重命名下
     */
    private appendFieldValueChangeEvents(propertyData: any, eventList: any[]) {
        // 若绑定了字段，则需要显示字段变更前后事件
        if (propertyData.binding && propertyData.binding.type === FormBindingType.Form && propertyData.binding.field) {
            const valueChangingExist = eventList.find(eventListItem => eventListItem.label === 'fieldValueChanging');
            if (!valueChangingExist) {
                eventList.push(
                    {
                        label: 'fieldValueChanging',
                        name: '绑定字段值变化前事件'
                    }
                );
            }
            const valueChangedExist = eventList.find(eventListItem => eventListItem.label === 'fieldValueChanged');
            if (!valueChangedExist) {
                eventList.push(
                    {
                        label: 'fieldValueChanged',
                        name: '绑定字段值变化后事件'
                    }
                );
            }
            if (this.dgVMField) {
                // 因为字段变更属性是存到VM中的，但是这里需要在控件上编辑，所以复制一份数据
                propertyData.fieldValueChanging = this.dgVMField.valueChanging;
                propertyData.fieldValueChanged = this.dgVMField.valueChanged;
            }


        } else {
            // 未绑定字段，则移除值变化事件
            eventList = eventList.filter(eventListItem => eventListItem.label !== 'fieldValueChanging' && eventListItem.label !== 'fieldValueChanged');
        }
    }

    private getControlMethodType(propertyData: any) {
        if (!propertyData.binding) {
            return propertyData.type;
        }
        switch (propertyData.binding.type) {
            case FormBindingType.Form: {
                return propertyData.binding.path || propertyData.type;
            }
            case FormBindingType.Variable: {
                return propertyData.binding.fullPath || propertyData.type;
            }
        }

        return propertyData.type;
    }
}
